package missObjects;

import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.logging.Logger;

import db.RawData;

public class RofTemplateObject extends RofMissionObject {

	private static Logger LOGGER = Logger.getLogger("RofLogger");

	public RofTemplateObject() {
		super();
		LOGGER.getUseParentHandlers();
	}

	/**
	 * Add a Generic Mission object by reading it form a path to a Rof template
	 * file
	 * 
	 * @param reader
	 *            BufferedReader to the Rof Template file
	 * @param mapName
	 *            : name of the map according to the template file
	 * @param groupName
	 *            : name of the group used in the file. If empty object to read
	 *            will not be in a group.
	 * @return the name of the current group name
	 * @throws Exception
	 *             on unidentified problem, ErrorRofFileReadingException on
	 *             syntax error in template file
	 */
	public int readFromFile(BufferedReader reader, String mapID, int fileID,
			int groupID) throws Exception, ErrorRofFileReadingException {
		this.mapID = mapID;
		this.fileID = fileID;

		String line = null;
		RawData rawLine = null; 
		int rawDataIndex=0;
		boolean endFlag = false;
		String tmp1 = null;
		String tmp2 = null;
		int groupIDReturned = groupID;

		do {
			try {
				line = reader.readLine();
				if (line == null) {
					this.objectType = null;
					endFlag = true;
					break;
				} else {
					// empty lines skipped
					if (!((line.trim()).equals(""))) {
						// first line is type of object
						switch (line.trim()) {
						case "Group":
							// Group processing
							//if (!(groupID == -1)) {
							if ((groupID == -10)) {
								// new group but last one not finished => error
								// TODO not working for nested groups !!!
								throw new ErrorRofFileReadingException(
										"Group format Error, line:" + line);
							} else {
								this.objectType = "Group";
								// one line {
								line = reader.readLine().trim();
								// one line Name + one line Index + One line
								// Desc
								String[] fieldsToRead = { "Name", "Index",
										"Desc", };
								for (String s : fieldsToRead) {
									line = reader.readLine().trim();
									try (Scanner scanner = new Scanner(line)) {
										scanner.useDelimiter("=|;");
										if (scanner.hasNext()) {
											// Name
											tmp1 = scanner.next().trim();
											tmp2 = scanner.next().trim();
										}
										switch (s) {
										case "Name":
											this.name = tmp2;
											break;
										case "Index":
											this.indexInfile = Integer
													.valueOf(tmp2);
											break;
										// Desc not used
										}
									}
								}
								groupIDReturned = this.indexInfile;
								endFlag = true;
								LOGGER.fine("Group read" + this.name + " ID"
										+ this.indexInfile);
							}
							break;
						case "{":
							// should never occured
							throw new ErrorRofFileReadingException(
									"Unexpected { Error, line:" + line);

						case "}":
							// End of group
							//TODO : not working for nested groups
							// if (groupID == -1) {
							if (groupID == -10) {
								throw new ErrorRofFileReadingException(
										"Unexpected } Error, line:" + line);
							} else {
								groupIDReturned = -1;
								this.objectType = "endOfGroup";
								endFlag = true;
							}
							break;

						default:
							// No Group Object processing
							int depthLevel = 0;
							endFlag = false;
							// informations to read until "}"
							this.objectType = line.trim();
							while (!endFlag) {
								line = reader.readLine().trim();
								try (Scanner scanner = new Scanner(line)) {
									scanner.useDelimiter("=|;");
									if (scanner.hasNext())
										tmp1 = scanner.next().trim();
									if (scanner.hasNext())
										tmp2 = scanner.next().trim();
									// reading of standard fields
									switch (tmp1) {
									case "{":
										depthLevel++;
										if (depthLevel > 1) {
											// nested declaration handling (at
											// least damage)
											// non processed datas are stored
											rawLine=new RawData(rawDataIndex, line);
											rawDataIndex++;
											this.unProcessedData.add(rawLine);
										}
										break;
									case "}":
										// end of object
										depthLevel--;
										if (depthLevel > 0) {
											// nested declaration handling (at
											// least damage)
											// non processed datas are stored
											
											rawLine=new RawData(rawDataIndex, line);
											rawDataIndex++;
											this.unProcessedData.add(rawLine);
											
										} else {
											endFlag = true;
										}
										break;
									case "Name":
										this.name = tmp2;
										break;
									case "Index":
										this.indexInfile = Integer
												.valueOf(tmp2);
										break;
									case "XPos":
										this.Xpos = Double.valueOf(tmp2);
										break;
									case "YPos":
										this.Ypos = Double.valueOf(tmp2);
										break;
									case "ZPos":
										this.Zpos = Double.valueOf(tmp2);
										break;
									case "XOri":
										this.Xori = Double.valueOf(tmp2);
										break;
									case "YOri":
										this.Yori = Double.valueOf(tmp2);
										break;
									case "ZOri":
										this.Zori = Double.valueOf(tmp2);
										break;
									case "Model":
										// only the model name is used, full
										// path is stored as unProcessData
										String[] modelStrings;
										modelStrings = tmp2.split("\\\\");
										this.model = "\""
												+ modelStrings[2].replace(
														".mgm", "");
										
										rawLine=new RawData(rawDataIndex, line);
										rawDataIndex++;
										this.unProcessedData.add(rawLine);
										break;
									default:
										// non processed datas are stored
										rawLine=new RawData(rawDataIndex, line);
										rawDataIndex++;
										this.unProcessedData.add(rawLine);
										break;
									}
								}
							}
							// end of block
							endFlag = true;
							this.groupID = groupID;
							LOGGER.fine("Object read: " + this.name + ", ID:"
									+ this.indexInfile + ", type: "
									+ this.objectType + ", group: "
									+ this.groupID);
						}
					}
				}

			} catch (Exception e) {
				LOGGER.severe(e.getClass().getName() + ": " + e.getMessage());
				throw (e);
			}
		} while (!endFlag);

		return groupIDReturned;
	}
}
